package com.cash.channel.svc.logic;

import com.alibaba.fastjson.JSON;
import com.cash.channel.api.constant.Constant;
import com.cash.channel.api.exception.CashChannelException;
import com.cash.channel.api.model.callback.*;
import com.cash.channel.api.model.cycle.AmountLimit;
import com.cash.channel.api.model.enums.ApplyAuditStatusEnum;
import com.cash.channel.api.model.repay.RepayPlanModel;
import com.cash.channel.api.model.repay.WdOrderInfoModel;
import com.cash.channel.api.model.user.ThirdIdModel;
import com.cash.channel.svc.model.ApplyWithdrawalFlow;
import geex.core.service.LoanService;
import geex.core.service.model.loan.Loan;
import geex.core.service.model.loan.RepayPlan;
import geex.trans.enums.RepayTypeEnum;
import geex.trans.model.RepayInAcctFlow;
import geex.trans.model.RepayResultAmqp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class CallBackLogic {

    @Autowired
    private ThirdCommonLogic thirdCommonLogic;

    @Autowired
    private RepayLogic repayLogic;

    @Autowired
    private LoanService loanService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderLogic orderLogic;

    public ApplyAuditStatusCallBack getApplyAuditStatusCallBackByAppId(Map<String, Object> orderMap, String channel) throws CashChannelException {
        try {
            String nQCAppStatus = MapUtils.getString(orderMap, "status");
            ApplyAuditStatusCallBack applyAuditStatusCallBack = new ApplyAuditStatusCallBack();
            applyAuditStatusCallBack.setOrderNo(thirdCommonLogic.findThirdIdModelByAppId(MapUtils.getString(orderMap, "appId"), channel).getCThirdId());
            switch (nQCAppStatus) {
                case "300":
                    AmountLimit limitAmt = repayLogic.getLimitAmt(MapUtils.getString(orderMap, "appId"), MapUtils.getString(orderMap, "uid"));
                    applyAuditStatusCallBack.setStatus(ApplyAuditStatusEnum.APPROVED.getStatus());
                    applyAuditStatusCallBack.setAmtRange(100);
                    applyAuditStatusCallBack.setMinLoanAmt(1000);
                    applyAuditStatusCallBack.setApproveTime(new Date(MapUtils.getLongValue(orderMap, "updateTime")).getTime());
                    applyAuditStatusCallBack.setMaxLoanAmt(limitAmt.getTotalAmount().intValue());
                    applyAuditStatusCallBack.setTermOptions(thirdCommonLogic.getLoanTermOption(channel));
                    applyAuditStatusCallBack.setAmountLimit(limitAmt);
                    Boolean flag= thirdCommonLogic.checkOrderStatus(MapUtils.getString(orderMap, "uid"),null);
                    if(!flag){
                        applyAuditStatusCallBack.setStatus(ApplyAuditStatusEnum.FROZEN.getStatus());
                    }
                    break;
                case "400":
                    applyAuditStatusCallBack.setStatus(ApplyAuditStatusEnum.REJECTED.getStatus());
                    break;
                default:
                    applyAuditStatusCallBack.setStatus(ApplyAuditStatusEnum.WAITING.getStatus());
                    break;
            }
            return applyAuditStatusCallBack;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取额度订单状态失败");
        }
    }

    public LoanStatusCallBack getLoanStatusCallBackByAppId(Map<String, Object> orderMap, String channel) throws CashChannelException {
        try {
            LoanStatusCallBack loanStatusCallBack = new LoanStatusCallBack();
            String wdId =MapUtils.getString(orderMap, "appId");
            WdOrderInfoModel wdOrderInfoModel = repayLogic.findWithdrawAppInfoByAppId(wdId);
            loanStatusCallBack.setLoanAmount(wdOrderInfoModel.getNWdAmt().setScale(2, RoundingMode.HALF_UP));
            loanStatusCallBack.setOrderStatus(wdOrderInfoModel.getNWdAppStatus().toString());
            loanStatusCallBack.setWithdrawId(wdOrderInfoModel.getCWdAppId());
            loanStatusCallBack.setOrderStatus(orderLogic.getOrderStatus(wdOrderInfoModel, null));
            if (1500 == wdOrderInfoModel.getNWdAppStatus()) {
                loanStatusCallBack.setRepayPlan(repayLogic.getRepayPlan(wdId));
                Loan loan = loanService.findLoanByExtId(wdOrderInfoModel.getCWdAppId());
                loanStatusCallBack.setLoanDate(loan.getLoanDate().getTime());
                loanStatusCallBack.setRepayPlan(repayLogic.getRepayPlan(wdId));
                loanStatusCallBack.setOrderStatus(orderLogic.getOrderStatus(wdOrderInfoModel, loan));
            }
            return loanStatusCallBack;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取提现订单状态失败");
        }
    }

    public RepayPlanListCallBack getRepayPlanListCallBackByAppId(Map<String, Object> map, String channel) throws CashChannelException {
        try {
            String wdId = MapUtils.getString(map, "appId");
            List<RepayPlan> repayPlanList = new ArrayList<>();
            Loan loan = loanService.findLoanByExtId(wdId);
            repayPlanList = loanService.getRepayPlanByExtId(wdId);
            if (repayPlanList.isEmpty()) {
                // FIXME: 2019/11/4 earlyRepay bankName
                throw new CashChannelException("暂无还款计划");
            }
            List<RepayPlanModel> repayPlanModelList = repayLogic.getRepayPlan(wdId);
            // FIXME: 2019/11/4 earlyRepay bankName
            return new RepayPlanListCallBack(wdId, 0, loan.getBankCode(), "", loan.getBankCard(), repayPlanModelList);
        } catch (CashChannelException e) {
            log.error(e.getErrMessage(), e);
            throw new CashChannelException("获取还款计划回调信息失败");
        }
    }
    public RepayStatusCallBack payStatusCallBack(RepayResultAmqp repayResultAmqp, String channel) throws CashChannelException {
        try {
            ApplyWithdrawalFlow applyWithdrawalFlow = repayLogic.getChannelByWdId(repayResultAmqp.getAppId());
            ThirdIdModel thirdIdModel = thirdCommonLogic.findThirdIdModelByThirdOrderId(applyWithdrawalFlow.getcThirdId(), channel);
            RepayStatusCallBack payStatusCallBack = new RepayStatusCallBack();
            payStatusCallBack.setWithdrawId(repayResultAmqp.getAppId());
            payStatusCallBack.setPeriod(repayResultAmqp.getTenor());
            payStatusCallBack.setOrderNo(applyWithdrawalFlow.getcThirdId());
            payStatusCallBack.setUserId(thirdIdModel.getCUserUid());
            payStatusCallBack.setChannel(channel);
            payStatusCallBack.setIsCustom(0);
            payStatusCallBack.setExtId(repayResultAmqp.getFlowNo());
            payStatusCallBack.setRepayType(getRepayType(repayResultAmqp.getRepayTypeEnum()));
            if(repayResultAmqp.getRepayDate()!=null){
                payStatusCallBack.setTime(repayResultAmqp.getRepayDate().getTime());
            }

            if (repayResultAmqp.getSuccessAmount() == null || (repayResultAmqp.getSuccessAmount() != null && repayResultAmqp.getSuccessAmount() == 0)) {
                log.info("syncDeductNotify 通知还款状态变更--失败通知");
                RepayStatus status =new RepayStatus();
                status.setStatus("40");
                status.setRemark(repayResultAmqp.getResMsg());
                payStatusCallBack.setData(status);
                rabbitTemplate.convertAndSend("geex" , Constant.ProConstant.CHANNEL_REPAY_STATUS_CALLBACK, JSON.toJSONString(payStatusCallBack));
            }
            if (repayResultAmqp.getRepayInAcctFlowList() != null && repayResultAmqp.getRepayInAcctFlowList().size() > 0) {
                for (RepayInAcctFlow repayInAcctFlow : repayResultAmqp.getRepayInAcctFlowList()) {
                    if (repayInAcctFlow.getFinishFlag()) {
                        //通知当期还款状态更新--还款成功
                        log.info("syncDeductNotify 通知还款状态变更--成功通知");
                        RepayStatus status =new RepayStatus();
                        status.setStatus("20");
                        status.setRemark("还款成功金额:" + new BigDecimal(repayInAcctFlow.getAllPayAmount()).setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                        payStatusCallBack.setData(status);
                        rabbitTemplate.convertAndSend("geex" , Constant.ProConstant.CHANNEL_REPAY_STATUS_CALLBACK, JSON.toJSONString(payStatusCallBack));
                    } else {
                        //部分还款成功，不做状态同步
                    }
                }
            }
            //判断是否需要通知还款计划同步--成功金额大于即需要同步还款计划
            if (repayResultAmqp.getSuccessAmount() != null && repayResultAmqp.getSuccessAmount() > 0) {
                log.info("syncDeductNotify 通知还款计划变更");
                Loan loan = loanService.findLoanByExtId(repayResultAmqp.getAppId());
                List<RepayPlanModel> repayPlanModelList = repayLogic.getRepayPlan(repayResultAmqp.getAppId());
                RepayPlanListCallBack repayPlanListCallBack = new RepayPlanListCallBack(applyWithdrawalFlow.getcThirdId(), 0, loan.getBankCode(), "", loan.getBankCard(), repayPlanModelList);
                repayPlanListCallBack.setChannel(channel);
                repayPlanListCallBack.setIsCustom(0);
                rabbitTemplate.convertAndSend("geex" , Constant.ProConstant.CHANNEL_REPAY_PLAN_SYN_CALLBACK, JSON.toJSONString(repayPlanListCallBack));
                //

            }
            log.info("syncDeductNotify end");
            return payStatusCallBack;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("获取提现订单状态失败");
        }
    }

    private Integer getRepayType(RepayTypeEnum repayTypeEnum) {
        switch (repayTypeEnum) {
            case 线上按期还款:
            case 线上提前结清:
                return 1;
            default:
                return 2;
        }
    }
}
